package cn.edu.scau.disk.controller;

import cn.edu.scau.disk.exception.CommonException;
import cn.edu.scau.disk.pojo.File;
import cn.edu.scau.disk.service.FileService;
import cn.edu.scau.disk.utils.R;
import cn.edu.scau.disk.utils.RedisConstant;
import cn.edu.scau.disk.utils.RedisUtil;
import cn.edu.scau.disk.utils.Token;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping("file")
@Validated
public class FileController {
    @Autowired
    FileService fileService;

    @Autowired
    RedisUtil redisUtil;

    String parse(String name){
        if (name==null) name="";
        byte[] tmp=name.getBytes();
        byte[] name_bytes=new byte[3];
        for (int i=0;i<3;i++){
            if (i<tmp.length) name_bytes[i]=tmp[i];
            else name_bytes[i]=' ';
        }
        return new String(name_bytes);
    }
    String parsedata(String data){
        if (data==null) data="";
        byte[] tmp=data.getBytes();
        byte[] data_bytes=new byte[tmp.length+1];
        for (int i=0;i<tmp.length;i++) data_bytes[i]=tmp[i];
        data_bytes[tmp.length]='@';
        return new String(data_bytes);
    }

    @Token
    @PostMapping("format")
    public R FormatAll(){
        fileService.FormatAll();
        return R.ok();
    }

    @PostMapping
    @Token
    public R create(String name, Integer parent_id, Integer type, @RequestHeader("token") String token) throws CommonException {
        try {
            System.err.println("艾欧尼亚");
            name= parse(name);
            fileService.FormFileSystem();
            Integer userid = Integer.valueOf(redisUtil.get(RedisConstant.TOKEN+token));
            fileService.CreateFile(parent_id, name, type, userid);
            fileService.DEBUG();
            return R.ok();
        } catch (CommonException e) {
            return R.fail(e.getLocalizedMessage()).put("mess",e.getMessage());
        }
    }

    @Token
    @PostMapping("{fid}/{name}")
    public R write(@PathVariable Integer fid, @PathVariable String name, String data) throws CommonException {
        try {
            name= parse(name);
            data= parsedata(data);
            fileService.FormFileSystem();
            fileService.WriteFile(fid, data,name);
            fileService.DEBUG();
            return R.ok();
        } catch (CommonException e) {
            return R.fail(e.getMessage());
        }
    }

    @Token
    @GetMapping("{fid}/{name}")
    public R read(@PathVariable Integer fid, @PathVariable String name) throws CommonException {
        try {
            name= parse(name);
            System.err.println(name+" here ");
            fileService.FormFileSystem();
            String body = fileService.ReadFile(fid, name);
            fileService.DEBUG();
            return R.ok().put("body", body);
        } catch (CommonException e) {
            return R.fail(e.getMessage());
        }
    }

    @Token
    @DeleteMapping
    public R delete(Integer fid,String namelist) throws CommonException {
        try {
            List<String> name_list= Arrays.asList(namelist.split(","));
            fileService.FormFileSystem();
            for (String name : name_list) {
                name= parse(name);
                fileService.Delete(fid, name);
            }
            fileService.DEBUG();
            return R.ok();
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    @Token
    @GetMapping
    public R listfile(String keyword) throws CommonException {
        if (keyword==null) keyword="";
        fileService.FormFileSystem();
        List<File> fileList = fileService.ListFile(keyword);
        fileService.DEBUG();
        return R.ok().put("fileList", fileList);
    }

    @Token
    @PutMapping
    public R rename(Integer fid, String oldname, String newname) throws CommonException {
        try {
            oldname=parse(oldname);
            newname=parse(newname);
            fileService.FormFileSystem();
            fileService.RenameFile(fid, oldname, newname);
            fileService.DEBUG();
            return R.ok();
        } catch (CommonException e) {
            return R.fail(e.getMessage());
        }
    }

    @Token
    @GetMapping("disklist")
    public R disklist(Integer fid, String name) throws CommonException {
        try {
            name= parse(name);
            fileService.FormFileSystem();
            File fileInfo = fileService.Showfileinfo(fid, name);
            List<Integer> diskList = fileService.ShowdiskList(fid, name);
            fileService.DEBUG();
            return R.ok().put("fileInfo", fileInfo)
                    .put("diskList", diskList);
        } catch (CommonException e) {
            return R.fail(e.getMessage());
        }
    }

    @Token
    @GetMapping("p")
    public R p(Integer fid,String keyword){
        try{
            fileService.FormFileSystem();
            if (keyword==null) keyword="";
            List<File> fileList=fileService.ListSingleFile(fid,keyword);
            return R.ok().put("fileList",fileList);
        }
        catch (CommonException e){
            return R.fail(e.getMessage());
        }
    }
    @Token
    @GetMapping("dirdisks")
    public R dirdisks(){
        try{
            fileService.FormFileSystem();
            List<Integer> disks=fileService.showDirDisks();
            return R.ok().put("disks",disks);
        }
        catch (Exception e){
            return R.fail(e.getMessage());
        }
    }

    @Token
    @GetMapping("disk")
    public R allDisk() throws CommonException {
        fileService.FormFileSystem();
        List<File> fileList=fileService.ListSingleFile(2,"");
        Set<Integer> diskList = new HashSet<>();
        for(File file : fileList){
            List<Integer> list = fileService.ShowdiskList(file.getParentId(), file.getName());
            diskList.addAll(list);
        }
        List<Integer> disks=fileService.showDirDisks();
        return R.ok().put("diskList",diskList).put("disks",disks);
    }
}
